package com.example.demo;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;

import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Description: Excel操作工具类
 */
@Slf4j
public class ExcelUtil {

    /**
     * 功能描述: 导出数据到Excel
     * <p>
     * 使用阿里easyPoi 自定义导出excel携带下拉框
     *
     * @param out         输出
     * @param list        需写入的数据
     * @param mapDropDown 下拉框数据
     */
    public static void exportBySelect(OutputStream out, List<?> list, Map<Integer, String[]> mapDropDown) {

        EasyExcelFactory.write(out, list.get(0).getClass()).registerWriteHandler(new EasyExcelSheetSelectUtils(mapDropDown)).sheet().doWrite(list);

    }


    /**
     * 功能描述: 导出数据到Excel
     * <p>
     * 使用阿里easyPoi 自定义导出excel携带下拉框
     *
     * @param out     输出
     * @param list    需写入的数据
     * @param content 水印参数
     */
    public static void exportBySelectHandler(OutputStream out, List<?> list, String content) {

        EasyExcelFactory.write(out, list.get(0).getClass()).inMemory(true).registerWriteHandler(new WaterMarkHandler(content)).sheet().doWrite(list);

    }

    /**
     * 根据模板导出excel
     * <p>
     * 支持简易循环填写excel
     *
     * @param templatePath  模板路径
     * @param temporaryName 临时文件名称
     * @param out           文件输出流
     * @param head          easyPoi 表头对象class
     * @param list          填充列表
     * @param col           导出类class
     * @param session       session
     */
    public static void exportTemplate(String templatePath, String temporaryName, OutputStream out, Class head, Class col, List<?> list, HttpSession session) throws IOException {
        String path = null;
        try {
            InputStream resourceAsStream = col.getClassLoader().getResourceAsStream(templatePath);
            path = ExcelUtil.getFilePath(temporaryName, resourceAsStream, session);
            Map<Integer, String[]> map = new HashMap<>();
            map.put(2, new String[]{"男", "女"});
            EasyExcel.write(out, head).needHead(false).withTemplate(path).registerWriteHandler(new EasyExcelSheetSelectUtils(map)).sheet().doWrite(list);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//删除临时文件
            if (path != null && !"".equals(path)) {
                File tempFile = new File(path);
                tempFile.delete();
                System.err.println("删除临时文件成功=====path:" + path);
            }
            out.close();
        }
    }

    /**
     * 根据模板导出excel
     * <p>
     * 支持列表循环填写excel
     * 以及填充excel中特殊标记的值
     *
     * @param templatePath  模板路径
     * @param temporaryName 临时文件名称
     * @param out           文件输出流
     * @param head          easyPoi 表头对象class
     * @param list          填充列表
     * @param col           导出类class
     * @param session       session
     * @param data          填充excel特殊单元格值
     */
    public static void exportTemplateByFill(String templatePath, String temporaryName, OutputStream out, Class head, Class col, List<?> list, Map<String, String> data, HttpSession session) throws IOException {
        String path = null;
        try {
            InputStream resourceAsStream = col.getClassLoader().getResourceAsStream(templatePath);
            path = ExcelUtil.getFilePath(temporaryName, resourceAsStream, session);
            ExcelWriter excelWriter = EasyExcel.write(out, head).needHead(false).withTemplate(path).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            //填充列表
            excelWriter.fill(list, writeSheet);
            //填充excel中特殊的单元格值
            excelWriter.fill(data, writeSheet);
            excelWriter.finish();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//删除临时文件
            if (StringUtils.isNotEmpty(path)) {
                File tempFile = new File(path);
                tempFile.delete();
                System.err.println("删除临时文件成功=====path:" + path);
            }
            out.close();
        }
    }

    /**
     * 根据模板导出excel
     * <p>
     * 支持列表循环填写excel
     * 以及填充多个sheet页，excel中特殊标记的值
     *
     * @param templatePath  模板路径
     * @param temporaryName 临时文件名称
     * @param out           文件输出流
     * @param col           导出类class
     * @param session       session
     * @param data          填充列表数据
     * @param otherData     填充excel特殊单元格值
     */
    public static void exportSheetsTemplateByFill(String templatePath, String temporaryName, OutputStream out, Class col, Map<String, List> data, Map<String, String> otherData, HttpSession session) throws IOException {
        String path = null;
        try {
            InputStream resourceAsStream = col.getClassLoader().getResourceAsStream(templatePath);
            path = ExcelUtil.getFilePath(temporaryName, resourceAsStream, session);
            ExcelWriter excelWriter = EasyExcel.write(out).withTemplate(path).build();
            Set<String> sheetNums = data.keySet();
            for (String num : sheetNums) {
                WriteSheet writeSheet = EasyExcel.writerSheet(Integer.parseInt(num)).build();
                FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
                //填充列表
                excelWriter.fill(data.get(num), fillConfig, writeSheet);
                //填充excel中特殊的单元格值
                excelWriter.fill(otherData, fillConfig, writeSheet);

            }
            excelWriter.finish();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//删除临时文件
            if (StringUtils.isNotEmpty(path)) {
                File tempFile = new File(path);
                tempFile.delete();
                System.err.println("删除临时文件成功=====path:" + path);
            }
            out.close();
        }
    }
//
//    /**
//     * 利用反射机制遍历对象的属性值，并放入单元格中，为excel添加样式
//     */
//    public static void fillExcelData(List<Student> list, List<Student2> list2, String[] headers, String[] headers2, String title, HttpServletResponse response) throws Exception {
//        // 创建工作薄
//        HSSFWorkbook wb = new HSSFWorkbook();
//        // 生成一个表格
//        HSSFSheet sheet = wb.createSheet(title);
//
//        // 设置表格默认宽度为15个字节
//        sheet.setDefaultColumnWidth((short) 25);
//
//        //颜色控制器
//        Map<String, Integer> colorMap = new HashMap<>();
//        int colorIndex = 10;//颜色索引
//        int moreColorIndex = 0;//超过索引
//
//        ExcelStyle excelStyle = new ExcelStyle(wb);
//        CellStyle style = excelStyle.getTitleStyle(wb);//获取标题样式
//        CellStyle style2 = excelStyle.getHeaderStyle(wb);//获取表头样式
//        CellStyle style3 = excelStyle.getHeaderExplainStyle(wb);//获取表头说明样式
//
//        // 标题
//        int rowIndex = 0;//行数索引
//        // 合并单元格0到headers.length -1行
//        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, headers.length - 1));
//        HSSFRow row0 = sheet.createRow(rowIndex++);
//        row0.setHeightInPoints(26);
//        HSSFCell cell1 = row0.createCell(0);
//        cell1.setCellStyle(style);
//        cell1.setCellValue(title);
//        for (short i = 1; i < headers.length; i++) {
//            HSSFCell cell = row0.createCell(i);
//            cell.setCellStyle(style);
//        }
//
//        // 合并单元格0到headers.length -2行
//        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, headers.length - 1));
//        //添加列表说明
//        HSSFRow row1 = sheet.createRow(rowIndex++);
//        row1.setHeightInPoints(16);
//        HSSFCell cell2 = row1.createCell(0);
//        cell2.setCellStyle(style3);
//        cell2.setCellValue("1.列表格式一");
//        for (short i = 1; i < headers.length; i++) {
//            HSSFCell cell = row1.createCell(i);
//            cell.setCellStyle(style3);
//        }
//
//        // 产生表格表头行
//        HSSFRow row = sheet.createRow(rowIndex++);
//        row.setHeightInPoints(20);
//        for (short i = 0; i < headers.length; i++) {
//            HSSFCell cell = row.createCell(i);
//            cell.setCellStyle(style2);
//            cell.setCellValue(headers[i]);
//        }
//
//        // 产生表格内容行
//        if (list != null && list.size() > 0) {
//            for (Student obj : list) {
//                // 利用反射得到对象的属性
//                Class cls = obj.getClass();
//                java.lang.reflect.Field[] flds = cls.getDeclaredFields(); // 得到私有属性
//                row = sheet.createRow(rowIndex++);
//                row.setHeightInPoints(30);//设置行高
//                CellStyle style4 = excelStyle.getListContentStyle(wb);//获取列表内容样式
//                //判断是否有相同成绩得学生
//                List<Student2> collect2 = list2.stream().filter(data -> data.getFraction().equals(obj.getFraction())).collect(Collectors.toList());
//                List<Student> collect1 = list.stream().filter(data -> data.getFraction().equals(obj.getFraction())).collect(Collectors.toList());
//                if (collect2.size() + collect1.size() > 1 && colorMap.get(String.valueOf(obj.getFraction())) == null) {
//                    colorMap.put(String.valueOf(obj.getFraction()), colorIndex);//加入颜色控制器
//                    colorIndex++;
//                    if (colorIndex == 27) {//调色板中..27,32-39的索引为空
//                        colorIndex++;
//                    }
//                    if (colorIndex > 31 && colorIndex < 40) {//调色板中.31-39的索引为空
//                        colorIndex = 40;
//                    }
//                    if (colorIndex > 64) {//调色板最大索引64
//                        moreColorIndex = 9;
//                    }
//                }
//
//                if (colorMap.get(String.valueOf(obj.getFraction())) != null || colorIndex > 64) {//超过调色板的项目数据底色都为白色
//                    style4.setFillForegroundColor(IndexedColors.fromInt(moreColorIndex == 0 ? colorMap.get(String.valueOf(obj.getFraction())) : moreColorIndex).index);
//                    style4.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//                }
//                for (int j = 0; j < headers.length; j++) {
//                    flds[j].setAccessible(true);
//                    HSSFCell cell = row.createCell(j);
//                    cell.setCellStyle(style4);
//                    cell.setCellValue((flds[j].get(obj)).toString());
//                }
//            }
//        }
//
//        //合并单元格
//        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, headers2.length - 1));
//        //添加列表说明
//        HSSFRow row2 = sheet.createRow(rowIndex++);
//        row2.setHeightInPoints(16);
//        HSSFCell cell3 = row2.createCell(0);
//        cell3.setCellStyle(style3);
//        cell3.setCellValue("1.列表格式二");
//        for (short i = 1; i < headers2.length; i++) {
//            HSSFCell cell = row2.createCell(i);
//            cell.setCellStyle(style3);
//        }
//
//        // 产生表头行
//        HSSFRow row_cy = sheet.createRow(rowIndex++);
//        row_cy.setHeightInPoints(20);
//        for (short i = 0; i < headers2.length; i++) {
//            HSSFCell cell = row_cy.createCell(i);
//            cell.setCellStyle(style2);
//            cell.setCellValue(headers2[i]);
//        }
//
//        // 产生表格内容行
//        if (list2 != null && list2.size() > 0) {
//            for (Student2 obj : list2) {
//                // 利用反射得到对象的属性
//                Class cls = obj.getClass();
//                java.lang.reflect.Field[] flds = cls.getDeclaredFields(); // 得到私有属性
//                row = sheet.createRow(rowIndex++);
//                row.setHeightInPoints(30);//设置行高
//                CellStyle style4 = excelStyle.getListContentStyle(wb);//获取列表内容样式
//                //判断是否有相同成绩得学生
//                List<Student2> collectCy = list2.stream().filter(data -> data.getFraction().equals(obj.getFraction())).collect(Collectors.toList());
//                if (collectCy.size() > 1 && colorMap.get(String.valueOf(obj.getFraction())) == null) {
//                    colorMap.put(String.valueOf(obj.getFraction()), colorIndex);//加入颜色控制器
//                    colorIndex++;
//                    if (colorIndex == 27) {//调色板中..27,32-39的索引为空
//                        colorIndex++;
//                    }
//                    if (colorIndex > 31 && colorIndex < 40) {//调色板中.31-39的索引为空
//                        colorIndex = 40;
//                    }
//                    if (colorIndex > 64) {//调色板最大索引64
//                        moreColorIndex = 9;
//                    }
//                }
//                if (colorMap.get(String.valueOf(obj.getFraction())) != null || colorIndex > 64) {//超过调色板的项目数据底色都为白色
//                    style4.setFillForegroundColor(IndexedColors.fromInt(moreColorIndex == 0 ? colorMap.get(String.valueOf(obj.getFraction())) : moreColorIndex).index);
//                    style4.setFillPattern(FillPatternType.SOLID_FOREGROUND);
//                }
////
//                for (int j = 0; j < headers2.length; j++) {
//                    flds[j].setAccessible(true);
//                    HSSFCell cell = row.createCell(j);
//                    cell.setCellStyle(style4);
//                    cell.setCellValue((flds[j].get(obj)).toString());
//                }
//            }
//        }
//
//        response.setContentType("multipart/form-data");
//        response.setCharacterEncoding("utf-8");
//        String fileName = "学生出成绩对比表" + ".xls";
//        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("gb2312"), "iso8859-1"));
//        response.setContentType("application/ynd.ms-excel;charset=UTF-8");
//        OutputStream out = response.getOutputStream();
//        wb.write(out);
//        out.flush();
//        out.close();
//    }

    /**
     * 获取临时文件路径
     *
     * @param inputStream
     * @param session
     * @param fileName
     * @return
     * @throws IOException
     */
    public static String getFilePath(String fileName, InputStream inputStream, HttpSession session) throws IOException {
        // 模板临时目录
        String rootPath = session.getServletContext().getRealPath("template/");
        // 临时文件路径名
        String filePath = rootPath + "_" + System.currentTimeMillis() + fileName;
        File tempFile = new File(filePath);
        // 保存到临时文件
        saveTempFile(inputStream, tempFile);
        return filePath;
    }



    // 保存到临时目录
    private static void saveTempFile(InputStream inputStream, File tempFile) throws IOException {
        if (!tempFile.getParentFile().exists()) { //如果文件的目录不存在
            tempFile.getParentFile().mkdirs(); //创建目录
        }
        OutputStream os = new FileOutputStream(tempFile);
        byte[] b = new byte[2048];
        int length;
        while ((length = inputStream.read(b)) > 0) {
            os.write(b, 0, length);
        }
        os.flush();
        os.close();
        inputStream.close();
    }

}
